﻿namespace NuGetCop.MSBuild.Tasks
{
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Xml.Linq;
    using System.Xml.XPath;
    using NuGetCop.MSBuild.Tasks.Foundation;

    internal sealed class NuGetPackageRepositoryFactory : INuGetPackageRepositoryFactory
    {
        public INuGetPackageRepository Create(string packageConfigFilePath)
        {
            var packageReferences = LoadPackages(packageConfigFilePath);

            var repository = new NuGetPackageRepository(packageReferences);
            return repository;
        }

        private static ReadOnlyCollection<INuGetPackageReference> LoadPackages(string packageConfigFilePath)
        {
            var packagesXml = XDocument.Load(packageConfigFilePath);

            var packageReferences = packagesXml
                .XPathSelectElements("packages/package")
                .Select(CreatePackageReference)
                .ToArray();

            return new ReadOnlyCollection<INuGetPackageReference>(packageReferences);
        }

        private static INuGetPackageReference CreatePackageReference(XElement packageConfig)
        {
            var packageReference = new NuGetPackageReference
                {
                    Id = GetAttribute(packageConfig, NuGetSpecification.PackageIdAttribute),
                    Version = GetAttribute(packageConfig, NuGetSpecification.PackageVersionAttribute),
                    TargetFramework = GetAttribute(packageConfig, NuGetSpecification.TargetFrameworkAttribute),
                }.AdjustBy(x => x.MakeReadOnly());

            return packageReference;
        }

        private static string GetAttribute(XElement node, XName requiredAttribute)
        {
            var attributeValue = node
                .Attribute(requiredAttribute)
                .Eval(x => x.Value);

            return attributeValue;
        }
    }
}